/** 三国战纪2群雄争霸

  经过mame插件测试,本作的下前,后下前存在斜下判定,
  必须有下和前,后和下同时按下的时间段!
  而三国战纪119则没有这种判定,下前a可以先按下再按前再按a
  
  增加了降将和转换,用Rctrl切换
  
  By setycyas @2024-03-16
*/

/* 全局设定
*/
#Warn
#MaxThreadsPerHotkey 1
SetWorkingDir(A_ScriptDir)
;导入自定义函数库
#Include "..\Class\OrderMap.2.ahk"
#Include "..\Class\MyFuns.2.ahk"
;导入宏相关函数和UI
#Include "..\Class\FaceDetector.2.ahk"
#Include "..\Class\CommonMacro.2.ahk"
#Include "..\Class\CommonUI.2.ahk"
#Include "..\Class\MyEmu.2.ahk"

SendMode("Input")

/* 制作三国战记2群雄争霸的宏类
*/
class Kov2PMacro extends CommonMacro {

  pressDuration := 40

  /* 技能函数 
  */
  
  /* 宏函数
  */
  
  ;局部的宏,不直接调用
  _下上(i){
    this._downDown()
    sleep(30)
    this._downUp()
    sleep(30)
    this._upDown()
    sleep(30)
    this._upUp()
    sleep(30)
    this._press(i)
  }
  _上下(i){
    this._upDown()
    sleep(50)
    this._upUp()
    sleep(50)
    this._downDown()
    sleep(30)
    this._downUp()
    sleep(50)
    this._press(i)
  }
  _前A连打(key, delays){ ;较为特别,按住key连打最多delays[]长度次
    local vk, i, delay
    ;前A
    this._faceDown()
    this._press(1)
    sleep(30)
    this._faceUp()
    ;按住键则连打
    vk := GetKeyVk(MyFuns.getHotkey(key))
    for i, delay in delays {
      sleep(delay)
      if (MyFuns.getVkState(vk)){
        this._press(1)
      } else {
        return
      }
    }
  }
  
  ;通用行动
  _前B(key){
    this._faceDown()
    ;sleep(30) ;30
    this._down(2)
    sleep(30)
    this._faceUp()
    this._up(2)
  }
  _前BA_150(key){ ;张飞适用的参数
    this._前B(key)
    sleep(150)
    this._press(1)
  }
  _前BA_250(key){ ;孔明适用的参数
    this._前B(key)
    sleep(250)
    this._press(1)
  }
  _蹲A(key){
    MyFuns.keyDown("down")
    sleep(30)
    this._down(2)
    sleep(30)
    this._up(2)
    MyFuns.keyUp("down")
    sleep(30)
    this._press(1)
    sleep(100)
  }
  
  ;A键技能
  _下前A(key){
    this._downDown()
    sleep(60)
    this._faceDown()
    sleep(30)
    this._downUp()
    sleep(50)
    this._faceUp()
    sleep(30)
    this._press(1)
  }
  _下上A(key){
    this._下上(1)
  }
  ;用mame的宏插件测试,赵云4次a的间隔(含按键持续时间)应该是15,15,18帧,
  ;每秒60帧
  _前A连打_赵云(key){ 
    static delays := [230, 230, 275]
    this._前A连打(key, delays)
  }
  _前A连打_貂蝉(key){ ;比敌人位置低一点才能踢4次
    static delays := [175, 175, 175]
    this._前A连打(key, delays)
  }
  _前A连打_马超(key){ ;一般都只能踢4次,第五次位置多半不对
    static delays := [200, 200, 200, 200]
    this._前A连打(key, delays)
  }
  
  ;B键技能
  /*
  _下前B(key){ ;测试发现与下前A优化略优不同
    this._downDown()
    sleep(50)
    this._faceDown()
    sleep(30)
    this._downUp()
    sleep(50)
    this._down(2)
    sleep(30)
    this._faceUp()
    sleep(30)
    this._up(2)
  }
  */
  _下前B(key){ ;测试发现与下前A优化略优不同,斜下时按B才对
    this._downDown()
    sleep(50)
    this._faceDown()
    sleep(50)
    this._down(2)
    sleep(30)
    this._downUp()
    sleep(30)
    this._faceUp()
    sleep(30)
    this._up(2)
  }
  _后前B(key){
    this._backDown()
    sleep(30)
    this._backUp()
    sleep(50)
    this._faceDown()
    sleep(30)
    this._faceUp()
    sleep(30)
    this._press(2)
  }
  _后前B_黄忠(key){
    local vk := GetKeyVk(MyFuns.getHotkey(key))
    this._后前B(key)
    this._down(1)
    while(MyFuns.getVkState(vk)){
      sleep(30)
    }
    this._up(1)
  }
  _下上B(key){
    this._下上(2)
  }
  _上下B(key){
    this._上下(2)
  }
  /*
  _后下前B(key){
    this._backDown()
    sleep(50)
    this._downDown()
    sleep(30)
    this._backUp()
    sleep(30)
    this._faceDown()
    sleep(30)
    this._downUp()
    sleep(30)
    this._down(2)
    sleep(30)
    this._faceUp()
    sleep(30)
    this._up(2)
  }
  */
  _后下前B(key){
    this._backDown()
    sleep(50)
    this._downDown()
    sleep(30)
    this._backUp()
    sleep(30)
    this._faceDown()
    sleep(80) ;testParams[1]
    this._down(2)
    sleep(30)
    this._downUp()
    sleep(30)
    this._faceUp()
    sleep(30)
    this._up(2)
  }

  ;密码,大陆与香港不同
  _十八人大陆(key){ ;模式选择中使用
    this._down(2)
    sleep(50)
    this._down(4)
    sleep(50)
    MyFuns.press("left", 50)
    sleep(50)
    MyFuns.press("left", 50)
    sleep(50)
    this._press(3)
    sleep(50)
    this._press(3)
    sleep(50)
    MyFuns.press("right", 50)
    sleep(50)
    this._up(2)
    sleep(50)
    this._up(4)
  }
  _真方天画戟大陆(key){ ;正马超处使用
    loop 12 {
      this._press(5)
      sleep(150)
    }
  }
  _全密码_大陆(key){ ;各位置都与真方天画戟一样所以代码都用真方天画戟的
    this._十八人大陆(key)
    sleep(100)
    MyFuns.press("down")
    sleep(100)
    this._press(1)
    sleep(6000) ;选择模式后的等待时间
    ;找正庞统,调虎符,资料把令旗和虎符弄反了
    loop 3 { 
      MyFuns.press("right")
      sleep(200)
    }
    sleep(2000)
    this._真方天画戟大陆(key)
    sleep(2000)
    ;找猛正马超,调真方天画戟
    MyFuns.press("right")
    sleep(200)
    this._真方天画戟大陆(key)
    sleep(2000)
    ;找莽张飞,调令旗
    loop 2 { 
      MyFuns.press("left")
      sleep(200)
    }
    MyFuns.press("down")
    sleep(200)
    this._真方天画戟大陆(key)
  }
  _十八人香港(key){ ;模式选择中使用
    this._down(3)
    sleep(50)
    this._down(4)
    sleep(50)
    MyFuns.press("right", 50)
    sleep(50)
    loop 3 {
      this._press(2)
      sleep(50)
    }
    MyFuns.press("left", 50)
    sleep(50)
    this._up(3)
    sleep(50)
    this._up(4)
  }
  _真方天画戟香港(key){ ;正孙权处使用
    loop 3 {
      this._press(2)
      sleep(50)
      this._press(4)
      sleep(50)
    }
  }
  _令旗香港(key){ ;猛黄忠处使用
    loop 3 {
      this._press(2)
      sleep(50)
      this._press(3)
      sleep(50)
    }
  }
  _虎符香港(key){ ;逆关羽处使用
    loop 3 {
      this._press(4)
      sleep(50)
      this._press(3)
      sleep(50)
    }
  }
  _全密码_香港(key){
    this._十八人香港(key)
    sleep(100)
    MyFuns.press("down")
    sleep(100)
    this._press(1)
    sleep(6000) ;选择模式后的等待时间
    ;找正孙权,调真方天画戟
    loop 5 { 
      MyFuns.press("right")
      sleep(200)
    }
    this._真方天画戟香港(key)
    sleep(2000)
    ;找猛黄忠,调令旗
    MyFuns.press("right")
    sleep(200)
    MyFuns.press("down")
    sleep(200)
    this._令旗香港(key)
    sleep(2000)
    loop 6 { ;找逆关羽,调虎符
      MyFuns.press("left")
      sleep(200)
    }
    this._虎符香港(key)
  }

  /* 重载宏接口
  */
  _setMacro(){
    static obm := ObjBindMethod
    local m ;this.macroMap的缩短版
    this.macroMap := OrderMap()
    m := this.macroMap
    m["连发A"] := obm(this, "_连发A")
    ;通用技能
    m["前B"] := obm(this, "_前B")
    m["前BA_150"] := obm(this, "_前BA_150")
    m["前BA_250"] := obm(this, "_前BA_250")
    m["蹲A"] := obm(this, "_蹲A")
    ;A键技能
    m["下前A"] := obm(this, "_下前A")
    m["下上A"] := obm(this, "_下上A")
    m["前A连打_赵云"] := obm(this, "_前A连打_赵云")
    m["前A连打_貂蝉"] := obm(this, "_前A连打_貂蝉")
    m["前A连打_马超"] := obm(this, "_前A连打_马超")
    ;B键技能
    m["下上B"] := obm(this, "_下上B")
    m["后前B"] := obm(this, "_后前B")
    m["后前B_黄忠"] := obm(this, "_后前B_黄忠")
    m["下前B"] := obm(this, "_下前B")
    m["上下B"] := obm(this, "_上下B")
    m["后下前B"] := obm(this, "_后下前B")
    ;密码,全密码在模式选择时光标对准简易模式用
    m["全密码_大陆"] := obm(this, "_全密码_大陆")
    m["全密码_香港"] := obm(this, "_全密码_香港")
    this.macroArr := m.getKeys()
  }

}

/* 制作三国战记2群雄争霸专用UI
*/
class Kov2PUI extends CommonUI {

  DEFAULT_HOTKEYS := "~d,~s,~e,~r,~g"
  EXE_ARRAY := [
    MyEmu.FBAS, MyEmu.XZONE, "MAME.exe"
  ]

  /* 构造函数
  */
  __New(macro){
    super.__New("三国战记2群雄争霸", macro)
    local p ;this._preset变量的缩短
    this._preset := OrderMap()
    this._lastPreset := "正孔明" ;切换降将与角色用的记录变量
    p := this._preset
    ;设定预设
    p["正庞统"] := ["连发A", "下前A", "下上A", "上下B", "后前B"]
    p["正孔明"] := ["连发A", "下前A", "前BA_250", "上下B", "后前B"]
    p["双貂蝉"] := ["连发A", "下上A", "前A连打_貂蝉", "下前B", "上下B"]
    p["隐庞统"] := ["连发A", "下前A", "下上A", "下上B", "上下B"]
    p["智孔明"] := ["连发A", "下前A", "后下前B", "上下B", "前B"]
    
    p["正赵云"] := ["连发A", "下上A", "前A连打_赵云", "后下前B", "后前B"]
    p["血赵云"] := ["连发A", "下上A", "前A连打_赵云", "下前B", "前B"]
    p["正关羽"] := ["连发A", "下前A", "下上A", "后前B", "后下前B"]
    p["正张飞"] := ["连发A", "下前A", "前BA_150", "下上B", "后下前B"]
    p["正马超"] := ["连发A", "下前A", "前A连打_马超", "上下B", "后下前B"]
    p["正黄忠"] := ["连发A", "下前A", "下上A", "下上B", "后前B_黄忠"]
    p["正孙权"] := ["连发A", "下上A", "下前A", "上下B", "蹲A"]
    p["降将"] := ["连发A", "下前A", "下上A", "下上B", "下前B"]
  }

  /* 重写接口
  */
  ;首次提交数据,暂时没有准备操作
  /*
  _onSubmitEnd(){
    super._onSubmitEnd()
    if (this._submitTimes == 0){
      HotIfWinActive(this._winTitle)
      Hotkey("RCtrl", this._changeCheatWeapon.bind(this))
      HotIfWinActive()
    }
  }
  */

  /* 重写setup,更改可选的exe,读入预设
  */
  setup(){
    super.setup()
    this._myGui.opt("+AlwaysOnTop")
    this._myGui.show("x1100 y330")
    this.readPresetMenu("正孔明")
  }

  /* 重写接口
  */
  ;首次提交数据时绑定RCtrl键为预设转换降将热键
  _onSubmitEnd(){
    super._onSubmitEnd()
    if (this._submitTimes == 0){
      HotIfWinActive(this._winTitle)
      Hotkey("RCtrl", this._changePreset.bind(this))
      HotIfWinActive()
    }
  }

  /* 重写读入预设函数,增加状态栏提示
  */
  readPresetMenu(itemName, itemPos := "", _menu := ""){
    super.readPresetMenu(itemName, itemPos, _menu)
    this._lastPreset := itemName
  }

  /* 预设转换,转换角色与降将,读入预设并无提示提交
  */
  _changePreset(key){
    static rolePreset := "正孔明" ;默认原角色
    ;上一预设不是降将,则转为降将并记录原角色
    ;若上一预设是降将,则转为原角色
    if(this._lastPreset != "降将" ){ 
      rolePreset := this._lastPreset
      this.readPresetMenu("降将")
    } else {
      this.readPresetMenu(rolePreset)
    }
    this.submit()
    this._statusBar.SetText(this._lastPreset)
  }

}

/* 运行当前脚本
*/
if (A_ScriptName == "三国战记2群雄争霸.2.ahk"){
  face := FaceDetector() ;方向检测对象
  macro := Kov2PMacro(face, ["q", "f", "v", "c", "z"]) ;宏对象,有界面时第二个参数可以随便写但长度不要小于2
  ;新建界面并设定
  ui := Kov2PUI(macro)
  ui.setup()
  ui._exeComboBox.Choose(MyEmu.FBAS)
  ui._gameKeyEdit.Text := "q,f,v,c,z" ; z是bcd组合键,调密码用
  ;ui._hotkeyEdit.Text := "~d,s,c,e,r,g"
  ui._fpsEdit.Text := 10
  ui.readPresetMenu("正孔明")
}